home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 42
/
Amiga Format AFCD42 (Issue 126, Aug 1999).iso
/
-serious-
/
comms
/
other
/
slrn
/
slrn_src
/
src
/
xover.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-14
|
15KB
|
737 lines
/* -*- mode: C; mode: fold; -*- */
/* Copyright (c) 1998 John E. Davis (davis@space.mit.edu)
*
* This file is part of slrn.
*
* Slrn is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* Slrn is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with Slrn; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#ifndef SLRNPULL_CODE
# include "slrnfeat.h"
#endif
#include <stdio.h>
#include <string.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include <slang.h>
#include "jdmacros.h"
#include "util.h"
#include "ttymsg.h"
#include "hash.h"
#ifndef SLRNPULL_CODE
# include "group.h"
# include "art.h"
#endif
#include "xover.h"
#ifndef SLRNPULL_CODE
static int extract_id_from_xref (char *);
#endif
typedef struct /*{{{*/
{
char *name;
unsigned int name_len;
char *value;
}
/*}}}*/
Header_Type;
#define MAX_PARSED_HEADERS 36
static Header_Type Parsed_Headers [MAX_PARSED_HEADERS] = /*{{{*/
{
#define SUBJECT_OFFSET 0
{"Subject", 7, NULL},
#define FROM_OFFSET 1
{"From", 4, NULL},
#define DATE_OFFSET 2
{"Date", 4, NULL},
#define MSGID_OFFSET 3
{"Message-ID", 10, NULL},
#define REFS_OFFSET 4
{"References", 10, NULL},
#define LINES_OFFSET 5
{"Lines", 5, NULL},
#define XREF_OFFSET 6
{"Xref", 4, NULL},
/* Technically, bytes is in the overview file. However, this value
* is not stored in slrn's article structure.
*/
#define BYTES_OFFSET 7
{"Bytes", 5, NULL}
#define NON_XOVER_HEADER_START 7
};
/*}}}*/
/* The pointers in the above structure will point to the following buffer. */
static char *Malloced_Headers;
static void parse_headers (void) /*{{{*/
{
unsigned int i;
unsigned int next_slot;
char *h, ch;
for (i = 0; i < NON_XOVER_HEADER_START; i++)
Parsed_Headers[i].value = NULL;
for (i = NON_XOVER_HEADER_START; i < MAX_PARSED_HEADERS; i++)
{
Parsed_Headers[i].name = NULL;
Parsed_Headers[i].value = NULL;
}
h = Malloced_Headers;
next_slot = NON_XOVER_HEADER_START;
while (*h != 0)
{
char *colon;
unsigned int len;
colon = h;
while (*colon && (*colon != ':')) colon++;
if (*colon != ':')
break;
*colon = 0;
len = (unsigned int) (colon - h);
colon++;
if (*colon == ' ') colon++; /* space is required to be there */
for (i = 0; i < NON_XOVER_HEADER_START; i++)
{
if ((Parsed_Headers[i].value != NULL)
|| (len != Parsed_Headers[i].name_len)
|| (slrn_case_strcmp ((unsigned char *)h,
(unsigned char *) Parsed_Headers[i].name)))
continue;
Parsed_Headers[i].value = colon;
break;
}
if ((i == NON_XOVER_HEADER_START) && (next_slot < MAX_PARSED_HEADERS))
{
/* Must not be an XOVER header. Add it to list. */
Parsed_Headers[next_slot].name = h;
Parsed_Headers[next_slot].name_len = len;
Parsed_Headers[next_slot].value = colon;
next_slot++;
}
/* Now skip to next header line and take care of continuation if
* present.
*/
h = colon;
while (0 != (ch = *h))
{
if (ch == '\n')
{
ch = *(h + 1);
if ((ch == ' ') || (ch == '\t'))
{
*h++ = ' ';
}
else
{
*h++ = 0;
break;
}
}
if (ch == '\t') *h = ' ';
h++;
}
}
}
/*}}}*/
#if SLRN_HAS_FAKE_REFS
static char *fake_refs_from_inreply_to (char *buf, unsigned int buflen)
{
char *p, ch;
Header_Type *h, *hmax;
h = Parsed_Headers + NON_XOVER_HEADER_START;
hmax = Parsed_Headers + MAX_PARSED_HEADERS;
while (1)
{
if ((h == hmax)
|| (NULL == (p = h->name)))
return NULL;
if ((11 == h->name_len)
&& (0 == slrn_case_strcmp ((unsigned char *)p, (unsigned char *)"In-Reply-To")))
break;
h++;
}
p = h->value;
while ((ch = *p) != 0)
{
unsigned int len;
char *pend;
if (ch != '<')
{
p++;
if ((ch == 'f') || (ch == 'F'))
{
/* heuristic: stop if we find 'From' or 'from'
* to avoid interpreting an email address as a
* message-id in cases like this:
* "In-Reply-To: A message from <olly@muscat.co.uk>"
*/
if (0 == strncmp (p, "rom", 3))
return NULL;
}
continue;
}
/* found a message-id */
if (NULL == (pend = slrn_strchr (p, '>')))
return NULL;
len = 1 + (pend - p); /* include the '>' */
if (len >= buflen)
return NULL;
strncpy (buf, p, len);
buf [len] = '\0';
return buf;
}
return NULL;
}
#endif
static int parsed_headers_to_xover (int id, Slrn_XOver_Type *xov) /*{{{*/
{
unsigned int len;
char *subj, *from, *date, *msgid, *refs, *bytes, *lines, *xref;
char *buf;
#if SLRN_HAS_FAKE_REFS
char fake_ref_buf [512];
#endif
if (NULL == (subj = Parsed_Headers[SUBJECT_OFFSET].value))
subj = "";
if (NULL == (from = Parsed_Headers[FROM_OFFSET].value))
from = "";
if (NULL == (date = Parsed_Headers[DATE_OFFSET].value))
date = "";
if (NULL == (msgid = Parsed_Headers[MSGID_OFFSET].value))
msgid = "";
if ((NULL == (refs = Parsed_Headers[REFS_OFFSET].value))
#if SLRN_HAS_FAKE_REFS
&& (NULL == (refs = fake_refs_from_inreply_to (fake_ref_buf, sizeof (fake_ref_buf))))
#endif
)
refs = "";
if (NULL == (xref = Parsed_Headers[XREF_OFFSET].value))
xref = "";
if (NULL == (lines = Parsed_Headers[LINES_OFFSET].value))
lines = "";
if (NULL == (bytes = Parsed_Headers[BYTES_OFFSET].value))
bytes = "";
len = strlen (subj) + strlen (from) + strlen (date) + strlen (msgid)
+ strlen (refs) + strlen (xref) + 6;
buf = slrn_malloc (len, 0, 1);
if (buf == NULL)
return -1;
xov->subject_malloced = buf;
strcpy (buf, subj);
buf += strlen (subj) + 1;
xov->from = buf;
strcpy (buf, from);
buf += strlen (from) + 1;
xov->date = buf;
strcpy (buf, date);
buf += strlen (date) + 1;
xov->message_id = buf;
strcpy (buf, msgid);
buf += strlen (msgid) + 1;
xov->references = buf;
strcpy (buf, refs);
buf += strlen (refs) + 1;
xov->xref = buf;
strcpy (buf, xref);
buf += strlen (xref) + 1;
xov->bytes = atoi (bytes);
xov->lines = atoi (lines);
#ifndef SLRNPULL_CODE
if (id == -1)
id = extract_id_from_xref (xov->xref);
#endif
xov->id = id;
return 0;
}
/*}}}*/
char *slrn_get_extra_xover_header (char *hdr) /*{{{*/
{
Header_Type *h, *hmax;
unsigned int len;
h = Parsed_Headers + NON_XOVER_HEADER_START;
hmax = Parsed_Headers + MAX_PARSED_HEADERS;
len = strlen (hdr);
while ((h < hmax) && (h->value != NULL))
{
if ((len == h->name_len)
&& (0 == slrn_case_strcmp ((unsigned char *)h->name,
(unsigned char *)hdr)))
return h->value;
h++;
}
return NULL;
}
/*}}}*/
#ifdef SLRNPULL_CODE
static int xover_parse_head (int id, char *headers, Slrn_XOver_Type *xov) /*{{{*/
{
slrn_free (Malloced_Headers);
if (NULL == (Malloced_Headers = slrn_strmalloc (headers, 1)))
return -1;
parse_headers ();
return parsed_headers_to_xover (id, xov);
}
/*}}}*/
#endif
void slrn_map_xover_to_header (Slrn_XOver_Type *xov, Slrn_Header_Type *h)
{
char *m;
h->subject = xov->subject_malloced;
h->number = xov->id;
h->from = xov->from;
h->date = xov->date;
h->refs = xov->references;
h->lines = xov->lines;
h->xref = xov->xref;
/* Since the subject has been malloced, the message_id pointer can be changed.
*/
m = xov->message_id;
while ((*m != '<') && (*m != 0))
m++;
if (*m != 0)
{
h->msgid = m;
m = slrn_strchr (m, '>');